package com.csun.dsms.service.impl;

import com.csun.dsms.comment.base.constant.GlobalConstant;
import com.csun.dsms.comment.base.enums.ErrorCodeEnum;
import com.csun.dsms.comment.base.exception.BusinessException;
import com.csun.dsms.comment.core.support.BaseService;
import com.csun.dsms.comment.core.support.CsunMessageSource;
import com.csun.dsms.mapper.DsmsRoleMapper;
import com.csun.dsms.model.domain.*;
import com.csun.dsms.model.dto.menu.MenuQueryDto;
import com.csun.dsms.model.dto.role.CheckRoleCodeDto;
import com.csun.dsms.model.dto.role.CheckRoleNameDto;
import com.csun.dsms.model.dto.role.RoleBindMenuDto;
import com.csun.dsms.model.enums.RoleStatusEnum;
import com.csun.dsms.model.vo.menu.BindAuthVo;
import com.csun.dsms.model.vo.role.RoleVo;
import com.csun.dsms.service.*;
import com.csun.dsms.utils.PublicUtil;
import com.github.pagehelper.PageHelper;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * @author chisj chisj@foxmail.com
 * @version 1.0.0
 * @date 2021-09-01 13:20
 * @description: TODO
 */
@Service
@Transactional
public class DsmsRoleServiceImpl extends BaseService<DsmsRole> implements DsmsRoleService {

    @Resource
    private DsmsRoleMapper dsmsRoleMapper;
    @Resource
    private DsmsMenuService dsmsMenuService;
    @Resource
    private CsunMessageSource csunMessageSource;
    @Resource
    private DsmsRoleUserService dsmsRoleUserService;
    @Resource
    private DsmsRoleMenuService dsmsRoleMenuService;
    @Resource
    private DsmsUnitService dsmsUnitService;

    /**
     * 校验角色编码是否已经存在
     *
     * @param checkRoleCodeDto	the check role code dto
     *
     * @return the boolean true-不存在, false-存在
     */
    @Override
    public boolean checkRoleCode(CheckRoleCodeDto checkRoleCodeDto) {

        Long id = checkRoleCodeDto.getRoleId();
        String roleCode = checkRoleCodeDto.getRoleCode();

        Example example = new Example(DsmsRole.class);
        Example.Criteria criteria = example.createCriteria();

        if (id != null) {
            criteria.andNotEqualTo("id", id);
        }
        criteria.andEqualTo("roleCode", roleCode);

        int result = selectCountByExample(example);

        return result < 1;
    }

    /**
     * 查询角色菜单列表
     *
     * @param menuQueryDto role menu query dto
     *
     * @return the dsms menu list.
     */
    @Override
    public List<DsmsMenu> queryRoleMenuListWithPage(MenuQueryDto menuQueryDto) {

        // 校验角色Id是否为空
        Preconditions.checkArgument(menuQueryDto.getRoleId() != null,
                csunMessageSource.getMessage("role.id.null", null));

        List<DsmsMenu> menuList = Lists.newArrayList();
        // 获取所有绑定的菜单和按钮权限Id集合
        List<Long> checkedAuthList = dsmsMenuService.getCheckedMenuList(menuQueryDto.getRoleId());

        // 分页
        PageHelper.startPage(menuQueryDto.getPageNum(), menuQueryDto.getPageSize());
        if (PublicUtil.isEmpty(checkedAuthList)) {
            menuList = dsmsMenuService.queryMenuAndSubMenuListWithPage(menuQueryDto);
        } else {
            menuQueryDto.setMenuIds(StringUtils.join(checkedAuthList, ","));
            // 查询
            menuList= dsmsMenuService.queryRoleMenuListWithPage(menuQueryDto);
        }

        return menuList;
    }

    /**
     * Gets menu tree by role id.
     *
     * @param roleId the role id
     *
     * @return the menu tree by role id
     */
    @Override
    public BindAuthVo getMenuTreeByRoleId(Long roleId) {

        BindAuthVo bindAuthVo = new BindAuthVo();
        Preconditions.checkArgument(roleId != null,
                csunMessageSource.getMessage("role.id.null", null));

        DsmsRole roleById = dsmsRoleMapper.selectByPrimaryKey(roleId);
        if (roleById == null) {
            throw new BusinessException(ErrorCodeEnum.GB10021001);
        }

        // 获取所有绑定的菜单和按钮权限Id集合
        List<Long> checkedAuthList = dsmsMenuService.getCheckedMenuList(roleId);

        return dsmsMenuService.getMenuTreeByMenuIdList(checkedAuthList);
    }

    /**
     * Query role list with page list.
     *
     * @param dsmsRole  the dsms role
     *
     * @return  the role vo list.
     */
    @Override
    public List<RoleVo> queryRoleListWithPage(DsmsRole dsmsRole) {

        return dsmsRoleMapper.queryRoleListWithPage(dsmsRole);
    }

    @Override
    public Integer deleteRoleById(Long id) {

        Preconditions.checkArgument(id != null,
                csunMessageSource.getMessage("role.id.null", null));

        // 判断角色是否存在
        DsmsRole dsmsRole = dsmsRoleMapper.selectByPrimaryKey(id);
        if (PublicUtil.isEmpty(dsmsRole)) {
            throw new BusinessException(ErrorCodeEnum.GB10021001);
        }

        // 超级管理员不能删除
        if (Objects.equals(id, GlobalConstant.Sys.SUPER_MANAGER_ROLE_ID)) {
            throw new BusinessException(ErrorCodeEnum.GB10021004);
        }

        // 绑定了用户不能删除
        DsmsRoleUser dsmsRoleUser = new DsmsRoleUser();
        dsmsRoleUser.setRoleId(id);
        int count = dsmsRoleUserService.selectCount(dsmsRoleUser);
        if (count > 0) {
            throw new BusinessException(ErrorCodeEnum.GB10021005);
        }

        // 绑定了菜单不能删除
        DsmsRoleMenu dsmsRoleMenu = new DsmsRoleMenu();
        dsmsRoleMenu.setRoleId(id);
        count = dsmsRoleMenuService.selectCount(dsmsRoleMenu);
        if (count > 0) {
            throw new BusinessException(ErrorCodeEnum.GB10021006);
        }

        return dsmsRoleMapper.deleteByPrimaryKey(id);
    }

    /**
     * 批量删除角色
     *
     * @param roleIdList  the role id list
     *
     * @return  the int.
     */
    @Override
    public Integer batchDeleteByIdList(List<Long> roleIdList) {

        Preconditions.checkArgument(PublicUtil.isNotEmpty(roleIdList), "删除角色ID不存在");

        List<DsmsRoleUser> ruList = dsmsRoleUserService.listByRoleIdList(roleIdList);
        if (PublicUtil.isNotEmpty(ruList)) {
            dsmsRoleUserService.deleteByRoleIdList(roleIdList);
        }

        dsmsRoleMenuService.deleteByRoleIdList(roleIdList);

        return dsmsRoleMapper.batchDeleteByIdList(roleIdList);
    }

    @Override
    public Integer editRole(DsmsRole dsmsRole, DsmsUser login) {

        // 校验角色是否存在
        DsmsRole roleQuery = dsmsRoleMapper.selectByPrimaryKey(dsmsRole.getId());
        if (PublicUtil.isEmpty(roleQuery)) {
            throw new BusinessException(ErrorCodeEnum.GB10021001);
        }

        // 校验角色编码是否唯一
        if (PublicUtil.isNotEmpty(dsmsRole.getRoleName())) {
            CheckRoleNameDto checkRoleNameDto = new CheckRoleNameDto();
            checkRoleNameDto.setRoleId(dsmsRole.getId());
            checkRoleNameDto.setRoleName(dsmsRole.getRoleName());
            if (!checkRoleName(checkRoleNameDto)) {
                throw new BusinessException(ErrorCodeEnum.GB10021008);
            }
        }

        // 校验角色编码是否唯一
        if (PublicUtil.isNotEmpty(dsmsRole.getRoleCode())) {
            // 判断是否相同
            if (!dsmsRole.getRoleCode().equals(roleQuery.getRoleCode())) {
                // 校验修改后的编码是否重复
                CheckRoleCodeDto checkRoleCodeDto = new CheckRoleCodeDto();
                checkRoleCodeDto.setRoleId(dsmsRole.getId());
                checkRoleCodeDto.setRoleCode(dsmsRole.getRoleCode());
                if (!checkRoleCode(checkRoleCodeDto)) {
                    throw new BusinessException(ErrorCodeEnum.GB10021007);
                }

                // 校验角色是否正在使用
                DsmsRoleUser dsmsRoleUser = new DsmsRoleUser();
                dsmsRoleUser.setRoleId(dsmsRole.getId());
                int count = dsmsRoleUserService.selectCount(dsmsRoleUser);
                if (count > 0) {
                    throw new BusinessException(ErrorCodeEnum.GB10021009);
                }
            }
        }

        if (PublicUtil.isNotEmpty(dsmsRole.getUnitId())) {
            // 校验单位id是否存在
            DsmsUnit dsmsUnit = dsmsUnitService.selectByKey(dsmsRole.getUnitId());
            if (PublicUtil.isEmpty(dsmsUnit)) {
                throw new BusinessException(ErrorCodeEnum.GB10031001);
            }
            dsmsRole.setUnitName(dsmsUnit.getName());
        }

        dsmsRole.setUpdateInfo(login);

        return dsmsRoleMapper.updateByPrimaryKeySelective(dsmsRole);
    }

    @Override
    public Integer saveRole(DsmsRole dsmsRole, DsmsUser login) {

        // 校验角色编码
        Preconditions.checkArgument(dsmsRole.getRoleCode() != null,
                csunMessageSource.getMessage("role.code.null", null));

        CheckRoleCodeDto checkRoleCodeDto = new CheckRoleCodeDto();
        checkRoleCodeDto.setRoleCode(dsmsRole.getRoleCode());
        if (!checkRoleCode(checkRoleCodeDto)) {
            throw new BusinessException(ErrorCodeEnum.GB10021007);
        }

        // 校验角色名称不能为空
        Preconditions.checkArgument(PublicUtil.isNotEmpty(dsmsRole.getRoleName()),
                csunMessageSource.getMessage("role.name.null", null));

        // 校验角色编码是否唯一
        CheckRoleNameDto checkRoleNameDto = new CheckRoleNameDto();
        checkRoleNameDto.setRoleName(dsmsRole.getRoleName());
        if (!checkRoleName(checkRoleNameDto)) {
            throw new BusinessException(ErrorCodeEnum.GB10021008);
        }

        // 校验单位id是否存在
        DsmsUnit dsmsUnit = dsmsUnitService.selectByKey(dsmsRole.getUnitId());
        if (PublicUtil.isEmpty(dsmsUnit)) {
            throw new BusinessException(ErrorCodeEnum.GB10031001);
        }
        dsmsRole.setUnitName(dsmsUnit.getName());

        dsmsRole.setStatus(RoleStatusEnum.ENABLE.getType());
        dsmsRole.setUpdateInfo(login);

        return dsmsRoleMapper.insertSelective(dsmsRole);
    }

    /**
     * 校验角色名称是否已经存在
     *
     * @param checkRoleNameDto	the check role name dto
     *
     * @return	the boolean true-不存在 false-存在
     */
    @Override
    public boolean checkRoleName(CheckRoleNameDto checkRoleNameDto) {

        Long id = checkRoleNameDto.getRoleId();
        String roleName = checkRoleNameDto.getRoleName();

        Example example = new Example(DsmsRole.class);
        Example.Criteria criteria = example.createCriteria();

        if (id != null) {
            criteria.andNotEqualTo("id", id);
        }
        criteria.andEqualTo("roleName", roleName);

        int result = selectCountByExample(example);

        return result < 1;
    }

    @Override
    public Integer bindMenu(RoleBindMenuDto roleBindMenuDto) {

        int result = 0;

        Long roleId = roleBindMenuDto.getRoleId();
        Set<Long> menuIdList = roleBindMenuDto.getMenuIdList();

        Preconditions.checkArgument(roleId != null,
                csunMessageSource.getMessage("role.id.null", null));

//        if (Objects.equals(roleId, GlobalConstant.Sys.SUPER_MANAGER_ROLE_ID)) {
//            logger.error("越权操作, 超级管理员用户不允许操作");
//            throw new UacBizException(ErrorCodeEnum.UAC10011023);
//        }

        DsmsRole dsmsRole = dsmsRoleMapper.selectByPrimaryKey(roleId);

        if (dsmsRole == null) {
            throw new BusinessException(ErrorCodeEnum.GB10021001);
        }

        dsmsRoleMenuService.deleteByRoleId(roleId);

        // menuSet actionIdList 如果为空则 取消该角色所有权限
        if (PublicUtil.isEmpty(menuIdList)) {
            logger.error("传入菜单权限Id为空, 取消菜单权限");
        } else {
            // 绑定菜单
            result = dsmsRoleMenuService.insert(roleId, menuIdList);
        }

        return result;
    }

    /**
     * 根据角色编码查询角色
     *
     * @param roleCode  the role code
     *
     * @return
     */
    @Override
    public DsmsRole selectByRoleCode(String roleCode) {

        DsmsRole dsmsRole = new DsmsRole();
        dsmsRole.setRoleCode(roleCode);

        return dsmsRoleMapper.selectOne(dsmsRole);
    }
}
